﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "ImportedObjectStylePage.h"
#include "TranslatorManager.h"
#include "GbmpNew.h"
#include "UniIdentity.h"
#include "IModelView.h"
#include "ICategory.h"
#include "ICategoryLibrary.h"
#include "IGraphicsStyle.h"
#include "IGraphicsStyleData.h"
#include "IGraphicsStyleDataOverrideItems.h"
#include "IDocument.h"
#include "IFamily.h"
#include "IInstance.h"
#include "IInstanceType.h"
#include "IElementBasicInformation.h"
#include "IGraphicsStyleManager.h"
#include "ILine3d.h"
#include "LineTypeDlg.h"
#include "LineStyleDlg.h"
#include "IUiDocumentViewManager.h"
#include "IUiDocument.h"
#include "IUiView.h"
#include "ILineTypeNew.h"
#include "ILineTypeData.h"

#include <QComboBox>
#include <QVBoxLayout>
#include <QTreeView>
#include <QColorDialog>
#include <QStandardItemModel>
#include <QUuid>
#include <QPainter>

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
using namespace gcmp;

static const UInt16 MaxLineWidth = 12;  // huanglw: 先拷贝到这里，应该暴露？

// Document Columns
#define COLUMN_IMPORTED_OBJECT  0
#define COLUMN_LINE_WIDTH       1
#define COLUMN_LINE_COLOR       2
#define COLUMN_LINE_TYPE        3

// Document Style Item Data Role
enum DocLineStyleItemDataRole
{
    DocLineStyleItemDataRole_CategoryId = Qt::UserRole + 1,
    DocLineStyleItemDataRole_Value,
    DocLineStyleItemDataRole_ValueChangedFlag
};

// Model View Columns
#define MV_COLUMN_IMPORTED_OBJECT   0
#define MV_COLUMN_PROJECT_LINE      1

// Model View Style Item Data Role
enum ModelViewLineStyleItemDataRole
{
    MVLineStyleItemDataRole_CategoryId = Qt::UserRole + 1,
    MVLineStyleItemDataRole_ObjectVisible,
    MVLineStyleItemDataRole_LineVisible,
    MVLineStyleItemDataRole_LineWidthInherited,
    MVLineStyleItemDataRole_LineWidth,
    MVLineStyleItemDataRole_LineColorInherited,
    MVLineStyleItemDataRole_LineColor,
    MVLineStyleItemDataRole_LineColorIsOverridden,
    MVLineStyleItemDataRole_LineTypeInherited,
    MVLineStyleItemDataRole_LineType,
    MVLineStyleItemDataRole_ValueChangedFlag
};

//////////////////////////////////////////////////////////////////////////
LineWidthItemComboxBoxDelegate::LineWidthItemComboxBoxDelegate(QObject* parent /* = nullptr */)
    : QStyledItemDelegate(parent)
{

}

QWidget *LineWidthItemComboxBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const  QModelIndex &index) const
{
    QComboBox *editor = NEW_AS_QT_CHILD(QComboBox, parent);
    FOR_EACH(itr, m_items)
    {
        editor->addItem(itr.second, itr.first);
    }
    return editor;
}

void LineWidthItemComboxBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString text = index.model()->data(index, Qt::DisplayRole).toString();
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    int curIndex = comboBox->findText(text);
    comboBox->setCurrentIndex(curIndex);
}

void LineWidthItemComboxBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const  QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    QString newText = comboBox->currentText();
    int newValue = comboBox->itemData(comboBox->currentIndex()).toInt();
    int currentValue = model->data(index, DocLineStyleItemDataRole_Value).toInt();
    if (newValue != currentValue)
    {
        model->setData(index, newValue, DocLineStyleItemDataRole_Value);
        model->setData(index, true, DocLineStyleItemDataRole_ValueChangedFlag);
        model->setData(index, newText, Qt::DisplayRole);
    }
}

void LineWidthItemComboxBoxDelegate::updateEditorGeometry(QWidget *editor, const  QStyleOptionViewItem &option, const  QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

//////////////////////////////////////////////////////////////////////////
ImportedObjectDocumentStylePage::ImportedObjectDocumentStylePage(QWidget* parent)
    : QWidget(parent)
{
    m_pTreeView = NEW_AS_QT_CHILD(QTreeView, this);
    m_pTreeView->setObjectName(QStringLiteral("ImportedObjectProjectTreeView"));
    m_pTreeView->setSelectionBehavior(QAbstractItemView::SelectItems);

    QVBoxLayout* pVLayout = NEW_AS_QT_CHILD(QVBoxLayout, this);
    pVLayout->addWidget(m_pTreeView);
    this->setLayout(pVLayout);

    m_pTreeModel = NEW_AS_QT_CHILD(QStandardItemModel, this);
}

QWidget* ImportedObjectDocumentStylePage::GetWidgetFW()
{
    return this;
}

std::wstring ImportedObjectDocumentStylePage::GetLabel() const
{
    return GBMP_TR(L"导入对象");
}

void ImportedObjectDocumentStylePage::OnApplied()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc, L"m_pDoc为空",L"GDMPLab",L"2024-03-30");

    std::vector<IModelView*> modelViews = IModelView::GetAllModelViews(m_pDoc);

    // apply all data changes
    for (int iObjectRow = 0; iObjectRow < m_pTreeModel->rowCount(); iObjectRow++)
    {
        QStandardItem* pObjectItem = m_pTreeModel->item(iObjectRow);
        DBG_WARN_AND_CONTINUE_UNLESS(pObjectItem, L"pObjectItem为空",L"GDMPLab",L"2024-03-30");

        for(int iLineStyleRow = 0; iLineStyleRow < pObjectItem->rowCount(); iLineStyleRow++)
        {
            QStandardItem* pLayerNameItem = pObjectItem->child(iLineStyleRow, COLUMN_IMPORTED_OBJECT);
            QStandardItem* pLineWidthItem = pObjectItem->child(iLineStyleRow, COLUMN_LINE_WIDTH);
            QStandardItem* pLineColorItem = pObjectItem->child(iLineStyleRow, COLUMN_LINE_COLOR);
            QStandardItem* pLineTypeItem = pObjectItem->child(iLineStyleRow, COLUMN_LINE_TYPE);
            DBG_WARN_AND_CONTINUE_UNLESS(pLayerNameItem && pLineWidthItem && pLineColorItem && pLineTypeItem, L"LineStyleItem为空",L"GDMPLab",L"2024-03-30");

            QVariant varCategoryId = pLayerNameItem->data(DocLineStyleItemDataRole_CategoryId);
            DBG_WARN_AND_CONTINUE_UNLESS(varCategoryId.isValid(), L"varCategoryId无效",L"GDMPLab",L"2024-03-30");
            UniIdentity categoryId(varCategoryId.toUuid());
            DBG_WARN_AND_CONTINUE_UNLESS(categoryId.IsValid(), L"categoryId无效",L"GDMPLab",L"2024-03-30");

            ElementId styleId = m_pDoc->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(categoryId);
            IGraphicsStyle* pDocStyleElement = quick_cast<IGraphicsStyle>(m_pDoc->GetElement(styleId));
            DBG_WARN_AND_CONTINUE_UNLESS(pDocStyleElement, L"pDocStyleElement为空",L"GDMPLab",L"2024-03-30");

            QVariant varLineWidthChanged = pLineWidthItem->data(DocLineStyleItemDataRole_ValueChangedFlag);
            if (varLineWidthChanged.isValid() && varLineWidthChanged.toBool())
            {
                OwnerPtr<IGraphicsStyleData> opGStyleData = pDocStyleElement->GetGraphicsStyleData();
                int newLineWidth = pLineWidthItem->data(DocLineStyleItemDataRole_Value).toInt();
                if (opGStyleData->GetProjectionLineWidth() != newLineWidth)
                {
                    opGStyleData->SetProjectionLineWidth(newLineWidth);
                    pDocStyleElement->SetGraphicsStyleData(*opGStyleData);

                    FOR_EACH(pCurModelView, modelViews)
                    {
                        DBG_WARN_AND_CONTINUE_UNLESS(pCurModelView, L"pCurModelView空指针",L"GDMPLab",L"2024-03-30");

                        // 获取该类别在modelview中的重载信息和数据
                        std::pair<OwnerPtr<IGraphicsStyleDataOverrideItems>, OwnerPtr<IGraphicsStyleData>> opCurViewGStyleTmp =
                            pCurModelView->GetGraphicsStyleOverrideByCategoryUid(pDocStyleElement->GetTargetCategoryUid());

                        // 如果没有任何字段重载，继续
                        if (opCurViewGStyleTmp.first->IsNoneOverridden())
                            continue;

                        // 重载数据
                        if (!opCurViewGStyleTmp.first->IsProjectionLineWidthOverridden())
                        {
                            opCurViewGStyleTmp.second->SetProjectionLineWidth(newLineWidth);
                            pCurModelView->OverrideGraphicsStyleByCategoryUid(pDocStyleElement->GetTargetCategoryUid(), *opCurViewGStyleTmp.first, *opCurViewGStyleTmp.second);
                        }
                    }
                }
            }

            QVariant varLineColorChanged = pLineColorItem->data(DocLineStyleItemDataRole_ValueChangedFlag);
            if (varLineColorChanged.isValid() && varLineColorChanged.toBool())
            {
                QVariant varNewLineColor = pLineColorItem->data(DocLineStyleItemDataRole_Value);
                QColor qcolor = varNewLineColor.value<QColor>();
                Color newLineColor(qcolor.red(), qcolor.green(), qcolor.blue());
                OwnerPtr<IGraphicsStyleData> opGStyleData = pDocStyleElement->GetGraphicsStyleData();
                if (opGStyleData->GetProjectionLineColor() != newLineColor)
                {
                    opGStyleData->SetProjectionLineColor(newLineColor);
                    pDocStyleElement->SetGraphicsStyleData(*opGStyleData);

                    FOR_EACH(pCurModelView, modelViews)
                    {
                        DBG_WARN_AND_CONTINUE_UNLESS(pCurModelView, L"pCurModelView空指针",L"GDMPLab",L"2024-03-30");

                        // 获取该类别在modelview中的重载信息和数据
                        std::pair<OwnerPtr<IGraphicsStyleDataOverrideItems>, OwnerPtr<IGraphicsStyleData>> opCurViewGStyleTmp =
                            pCurModelView->GetGraphicsStyleOverrideByCategoryUid(pDocStyleElement->GetTargetCategoryUid());

                        // 如果没有任何字段重载，继续
                        if (opCurViewGStyleTmp.first->IsNoneOverridden())
                            continue;

                        // 重载数据
                        if (!opCurViewGStyleTmp.first->IsProjectionLineColorOverridden())
                        {
                            opCurViewGStyleTmp.second->SetProjectionLineColor(newLineColor);
                            pCurModelView->OverrideGraphicsStyleByCategoryUid(pDocStyleElement->GetTargetCategoryUid(), *opCurViewGStyleTmp.first, *opCurViewGStyleTmp.second);
                        }
                    }
                }
            }

            QVariant varLineTypeChanged = pLineTypeItem->data(DocLineStyleItemDataRole_ValueChangedFlag);
            if (varLineTypeChanged.isValid() && varLineTypeChanged.toBool())
            {
                OwnerPtr<IGraphicsStyleData> opGStyleData = pDocStyleElement->GetGraphicsStyleData();
                std::wstring newLineType = pLineTypeItem->data(DocLineStyleItemDataRole_Value).toString().toStdWString();
                if (opGStyleData->GetProjectionLineTypeName() != newLineType)
                {
                    opGStyleData->SetProjectionLineTypeName(newLineType);
                    pDocStyleElement->SetGraphicsStyleData(*opGStyleData);

                    FOR_EACH(pCurModelView, modelViews)
                    {
                        DBG_WARN_AND_CONTINUE_UNLESS(pCurModelView, L"pCurModelView空指针",L"GDMPLab",L"2024-03-30");

                        // 获取该类别在modelview中的重载信息和数据
                        std::pair<OwnerPtr<IGraphicsStyleDataOverrideItems>, OwnerPtr<IGraphicsStyleData>> opCurViewGStyleTmp =
                            pCurModelView->GetGraphicsStyleOverrideByCategoryUid(pDocStyleElement->GetTargetCategoryUid());

                        // 如果没有任何字段重载，继续
                        if (opCurViewGStyleTmp.first->IsNoneOverridden())
                            continue;

                        // 重载数据
                        if (!opCurViewGStyleTmp.first->IsProjectionLineTypeNameOverridden())
                        {
                            opCurViewGStyleTmp.second->SetProjectionLineTypeName(newLineType);
                            pCurModelView->OverrideGraphicsStyleByCategoryUid(pDocStyleElement->GetTargetCategoryUid(), *opCurViewGStyleTmp.first, *opCurViewGStyleTmp.second);
                        }
                    }                   
                }
            }
        }
    }
}

bool ImportedObjectDocumentStylePage::InitUI(IDocument* pDoc, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories)
{
    m_pDoc = pDoc;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_pDoc, L"m_pDoc为空",L"GDMPLab",L"2024-03-30");

    std::list<ImportedObjectStyleData> objectStyles;
    bool bOk = ImportedObjectStylePageUtils::GetProjectContent(m_pDoc, categories, objectStyles);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"获取Style失败",L"GDMPLab",L"2024-03-30");

    bOk = BuildTreeModel(objectStyles);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"BuildTreeModel失败",L"GDMPLab",L"2024-03-30");

    bOk = SetDelegates();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"SetDelegates失败",L"GDMPLab",L"2024-03-30");

    return true;
}

bool ImportedObjectDocumentStylePage::BuildTreeModel(const std::list<ImportedObjectStyleData>& objectStyles)
{
    m_pTreeModel->clear();

    m_pTreeModel->setColumnCount(4);
    m_pTreeModel->setHeaderData(COLUMN_IMPORTED_OBJECT, Qt::Horizontal, QString::fromStdWString(GBMP_TR(L"导入对象")));
    m_pTreeModel->setHeaderData(COLUMN_LINE_WIDTH, Qt::Horizontal, QString::fromStdWString(GBMP_TR(L"线宽")));
    m_pTreeModel->setHeaderData(COLUMN_LINE_COLOR, Qt::Horizontal, QString::fromStdWString(GBMP_TR(L"线颜色")));
    m_pTreeModel->setHeaderData(COLUMN_LINE_TYPE, Qt::Horizontal, QString::fromStdWString(GBMP_TR(L"线型")));

    int objectRowIndex = 0;
    FOR_EACH(itrObject, objectStyles)
    {
        const std::wstring& objectName = itrObject.ObjectName;

        OwnerPtr<QStandardItem> opObjectItem = NEW_AS_OWNER_PTR(QStandardItem, QString::fromStdWString(objectName));
        opObjectItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);

        int layerRowIndex = 0;
        FOR_EACH(itrLineStyle, itrObject.LineStyles)
        {
            const UniIdentity& categoryId = itrLineStyle.CategoryId;
            QUuid categoryUid(categoryId.GetGuid());

            OwnerPtr<QStandardItem> opLayerNameItem = NEW_AS_OWNER_PTR(QStandardItem, QString::fromStdWString(itrLineStyle.LayerName));
            opLayerNameItem->setData(categoryUid, DocLineStyleItemDataRole_CategoryId);
            opLayerNameItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
            opObjectItem->setChild(layerRowIndex, COLUMN_IMPORTED_OBJECT, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opLayerNameItem));

            std::wstring displayLineWidth = StringUtil::ToWString(itrLineStyle.LineWidth);
            double valueLineWidth = itrLineStyle.LineWidth;
            OwnerPtr<QStandardItem> opLineWidthItem = NEW_AS_OWNER_PTR(QStandardItem, QString::fromStdWString(displayLineWidth));
            opLineWidthItem->setData(valueLineWidth, DocLineStyleItemDataRole_Value);
            opObjectItem->setChild(layerRowIndex, COLUMN_LINE_WIDTH, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opLineWidthItem));

            OwnerPtr<QStandardItem> opLineColorItem = NEW_AS_OWNER_PTR(QStandardItem);
            QColor color(itrLineStyle.LineColor.R, itrLineStyle.LineColor.G, itrLineStyle.LineColor.B);
            opLineColorItem->setData(color, DocLineStyleItemDataRole_Value);
            opLineColorItem->setFlags(Qt::NoItemFlags);
            opLineColorItem->setBackground(QBrush(color));
            opObjectItem->setChild(layerRowIndex, COLUMN_LINE_COLOR, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opLineColorItem));

            std::wstring displayLineType = itrLineStyle.LineType;
            std::wstring valueLineType = itrLineStyle.LineType;
            OwnerPtr<QStandardItem> opLineTypeItem = NEW_AS_OWNER_PTR(QStandardItem, QString::fromStdWString(displayLineType));
            opLineTypeItem->setData(QString::fromStdWString(valueLineType), DocLineStyleItemDataRole_Value);
            opLineTypeItem->setFlags(Qt::ItemIsEnabled);
            opObjectItem->setChild(layerRowIndex, COLUMN_LINE_TYPE, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opLineTypeItem));

            layerRowIndex++;
        }

        m_pTreeModel->setItem(objectRowIndex, COLUMN_IMPORTED_OBJECT, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opObjectItem));
        {
            OwnerPtr<QStandardItem> opDummyWidthItem = NEW_AS_OWNER_PTR(QStandardItem);
            opDummyWidthItem->setFlags(Qt::NoItemFlags);
            m_pTreeModel->setItem(objectRowIndex, COLUMN_LINE_WIDTH, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opDummyWidthItem));
            OwnerPtr<QStandardItem> opDummyColorItem = NEW_AS_OWNER_PTR(QStandardItem);
            opDummyColorItem->setFlags(Qt::NoItemFlags);
            m_pTreeModel->setItem(objectRowIndex, COLUMN_LINE_COLOR, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opDummyColorItem));
            OwnerPtr<QStandardItem> opDummyLineTypeItem = NEW_AS_OWNER_PTR(QStandardItem);
            opDummyLineTypeItem->setFlags(Qt::NoItemFlags);
            m_pTreeModel->setItem(objectRowIndex, COLUMN_LINE_TYPE, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opDummyLineTypeItem));
        }

        objectRowIndex++;
    }

    connect(m_pTreeModel, &QStandardItemModel::itemChanged, this, &ImportedObjectDocumentStylePage::OnItemDataChanged);

    m_pTreeView->setModel(m_pTreeModel);
    return true;
}

bool ImportedObjectDocumentStylePage::SetDelegates()
{
    // line width
    std::map<int, QString> lineWidthList;
    for (int i = 1; i <= (int)(MaxLineWidth); ++i)
    {
        lineWidthList.insert(std::make_pair(i, QString::number(i, 10)));
    }
    LineWidthItemComboxBoxDelegate* pLineWidthItemDelegate = NEW_AS_QT_CHILD(LineWidthItemComboxBoxDelegate, this);
    pLineWidthItemDelegate->SetItems(lineWidthList);
    m_pTreeView->setItemDelegateForColumn(COLUMN_LINE_WIDTH, pLineWidthItemDelegate);

    // line color
    // line type
    connect(m_pTreeView, &QTreeView::clicked, this, &ImportedObjectDocumentStylePage::OnItemClicked);

    return true;
}

void ImportedObjectDocumentStylePage::OnItemClicked(const QModelIndex& index)
{
    if (index.column() == COLUMN_LINE_COLOR)
    {
        QStandardItem* pItem = m_pTreeModel->itemFromIndex(index);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pItem, L"pItem为空",L"GDMPLab",L"2024-03-30");

        QVariant varValue = pItem->data(DocLineStyleItemDataRole_Value);
        if (!varValue.isValid())
            return;

        QColor currentColor = varValue.value<QColor>();

        QColorDialog dlg;
        dlg.setCurrentColor(currentColor);
        if (dlg.exec() == QDialog::Accepted)
        {
            QColor selectedColor = dlg.selectedColor();
            if (selectedColor != currentColor)
            {
                m_pTreeModel->setData(index, selectedColor, DocLineStyleItemDataRole_Value);
                m_pTreeModel->setData(index, true, DocLineStyleItemDataRole_ValueChangedFlag);
                pItem->setBackground(QBrush(selectedColor));
            }
        }
    }
    else if (index.column() == COLUMN_LINE_TYPE)
    {
        QStandardItem* pItem = m_pTreeModel->itemFromIndex(index);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pItem, L"pItem为空",L"GDMPLab",L"2024-03-30");

        QVariant varValue = pItem->data(DocLineStyleItemDataRole_Value);
        if (!varValue.isValid())
            return;

        QString currentLineType = varValue.toString();

        LineTypeDlg dlg(this);
        if (dlg.exec() == QDialog::Accepted)
        {
            QString selectedLineType = dlg.GetSelectLineTypeName();
            if (selectedLineType != currentLineType)
            {
                m_pTreeModel->setData(index, selectedLineType, DocLineStyleItemDataRole_Value);
                m_pTreeModel->setData(index, true, DocLineStyleItemDataRole_ValueChangedFlag);
                m_pTreeModel->setData(index, selectedLineType, Qt::DisplayRole);
            }
        }
    }
}

void ImportedObjectDocumentStylePage::OnItemDataChanged(QStandardItem *item)
{
    // mark the row as dirty
}

//////////////////////////////////////////////////////////////////////////
class LineStyleItemDelegate : public QStyledItemDelegate
{
public:
    LineStyleItemDelegate(QObject *parent = 0)
        : QStyledItemDelegate(parent)
    {
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QVariant varLineWidthInherited = index.data(MVLineStyleItemDataRole_LineWidthInherited);
        QVariant varLineWidth = index.data(MVLineStyleItemDataRole_LineWidth);
        QVariant varLineColorInherited = index.data(MVLineStyleItemDataRole_LineColorInherited);
        QVariant varLineColorIsOverridden = index.data(MVLineStyleItemDataRole_LineColorIsOverridden);
        QVariant varLineColor = index.data(MVLineStyleItemDataRole_LineColor);
        QVariant varLineTypeInherited = index.data(MVLineStyleItemDataRole_LineTypeInherited);
        QVariant varLineType = index.data(MVLineStyleItemDataRole_LineType);

        if (!varLineWidthInherited.isValid() || !varLineWidth.isValid() || !varLineColorInherited.isValid() || !varLineColorIsOverridden.isValid() ||
            !varLineColor.isValid() || !varLineTypeInherited.isValid() || !varLineType.isValid())
            return;

        int lineWidthInherited = varLineWidthInherited.toInt();
        int lineWidth = varLineWidth.toInt();

        QColor qcolorInherited = varLineColorInherited.value<QColor>();
        QColor qcolor = varLineColor.value<QColor>();
        Color lineColorInherited(qcolorInherited.red(), qcolorInherited.green(), qcolorInherited.blue());
        Color lineColor(qcolor.red(), qcolor.green(), qcolor.blue());
        bool lineColorIsOverridden = varLineColorIsOverridden.toBool();

        std::wstring lineTypeInherited = varLineTypeInherited.toString().toStdWString();
        std::wstring lineType = varLineType.toString().toStdWString();

        if (lineWidth == -1 && !lineColorIsOverridden && lineType.empty())
        {
            painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, QString::fromStdWString(GBMP_TR(L"无替换")));
            return;
        }

        painter->save();

        QPen pen;
        pen.setColor(lineColorIsOverridden? qcolor : qcolorInherited);
        pen.setWidth(lineWidth == -1? lineWidthInherited : lineWidth);
        painter->setPen(pen);

        std::vector<Vector3d> vertexList, pointList;
        {
            // 构造待离散的预览直线
            double height = (option.rect.top() + option.rect.bottom()) * 0.5;
            OwnerPtr<ILine3d> lineToDiscrete = ILine3d::Create(Vector3d(option.rect.left(), height, 0.0), Vector3d(option.rect.right(), height, 0.0));

            std::wstring strLineType = lineType.empty()? lineTypeInherited : lineType;

            // 通过线型名字，获得线型对象
            //OwnerPtr<ILineType> opLineType = ILineType::GetLineType(strLineType);
            //DBG_WARN_AND_RETURN_VOID_UNLESS(opLineType.get(), L"LineType is null", L"GDMPLab", L"2023-12-20");

            //if (opLineType.get() != nullptr)
            //{
            //    // 经验值？
            //    double tmpScale = -1.0;
            //    opLineType->Discrete(lineToDiscrete.get(), tmpScale, vertexList, pointList);
            //}
            IUiDocumentViewManager* pUiDocumentViewManager = IUiDocumentViewManager::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocumentViewManager, L"pUiDocumentViewManager为空",L"GDMPLab",L"2024-03-30");
            IUiView* pUIView = pUiDocumentViewManager->GetCurrentUiView();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pUIView, L"pUIView为空",L"GDMPLab",L"2024-03-30");
            IUiDocument* pUIDoc = pUIView->GetUiDocument();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc, L"pUIDoc为空",L"GDMPLab",L"2024-03-30");
            IDocument* pDoc = pUIDoc->GetDbDocument();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
            const ILineTypeNew* pLineType = ILineTypeNew::GetLineTypeByName(pDoc, strLineType);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pLineType, L"没找到对应线型",L"GDMPLab",L"2024-03-30");
            const ILineTypeData* plnTypeData = pLineType->GetLineTypeData();
            DBG_WARN_AND_RETURN_VOID_UNLESS(plnTypeData, L"ILineTypeData为空",L"GDMPLab",L"2024-03-30");
            std::vector<Vector3d> vertexList, pointList;
            plnTypeData->Discrete(lineToDiscrete.get(), -1.0, vertexList, pointList);
        }

        if (!vertexList.empty())
        {
            for (int i = 0; i < (int)vertexList.size() - 1;)
            {
                painter->drawLine(QPointF(vertexList[i].X(), vertexList[i].Y()), QPointF(vertexList[i + 1].X(), vertexList[i + 1].Y()));
                i += 2;
            }
        }

        QVector<QPointF> qPointList;
        FOR_EACH(pt, pointList)
        {
            qPointList.push_back(QPointF(pt.X(), pt.Y()));
        }
        painter->drawPoints(qPointList);

        painter->restore();
        QStyledItemDelegate::paint(painter, option, index);
    }
};

//////////////////////////////////////////////////////////////////////////
ImportedObjectModelViewStylePage::ImportedObjectModelViewStylePage(QWidget* parent)
    : QWidget(parent)
{
    m_pTreeView = NEW_AS_QT_CHILD(QTreeView, this);
    m_pTreeView->setObjectName(QStringLiteral("ImportedObjectModelViewTreeView"));
    m_pTreeView->setSelectionBehavior(QAbstractItemView::SelectItems);

    QVBoxLayout* pVLayout = NEW_AS_QT_CHILD(QVBoxLayout, this);
    pVLayout->addWidget(m_pTreeView);
    this->setLayout(pVLayout);

    m_pTreeModel = NEW_AS_QT_CHILD(QStandardItemModel, this);
}

QWidget* ImportedObjectModelViewStylePage::GetWidgetFW()
{
    return this;
}

std::wstring ImportedObjectModelViewStylePage::GetLabel() const
{
    return GBMP_TR(L"导入对象");
}

IDocument* ImportedObjectModelViewStylePage::GetDoc()
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_pCurrentModelView, L"m_pCurrentModelView为空",L"GDMPLab",L"2024-03-30");
    return m_pCurrentModelView->GetDocument();
}

void ImportedObjectModelViewStylePage::OnApplied()
{
    IDocument* pDoc = GetDoc();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    // apply all data changes
    for (int iObjectRow = 0; iObjectRow < m_pTreeModel->rowCount(); iObjectRow++)
    {
        QStandardItem* pObjectItem = m_pTreeModel->item(iObjectRow);
        DBG_WARN_AND_CONTINUE_UNLESS(pObjectItem, L"pObjectItem为空",L"GDMPLab",L"2024-03-30");

        // dxf object visibility changes?
        QVariant varObjectChanged = pObjectItem->data(MVLineStyleItemDataRole_ValueChangedFlag);
        if (varObjectChanged.isValid())
        {
            const std::wstring objectName = pObjectItem->text().toStdWString();
            bool objectVisible = pObjectItem->data(MVLineStyleItemDataRole_ObjectVisible).toBool();
            IFamily* pFamily = IFamily::GetFamilyByName(pDoc, objectName);
            if (pFamily)
            {
                auto instanceTypes = pFamily->GetInstanceTypes();
                FOR_EACH(itrInstanceType, instanceTypes)
                {
                    auto instances = itrInstanceType->GetAllInstances();
                    FOR_EACH(itrInstance, instances)
                    {
                        if (objectVisible)
                        {
                            m_pCurrentModelView->SetElementVisibilityByElementId(itrInstance->GetBasicInformation()->GetElementId(), true);
                        }
                        else
                        {
                            m_pCurrentModelView->SetElementVisibilityByElementId(itrInstance->GetBasicInformation()->GetElementId(), false);
                        }
                    }
                }
            }
        }

        for(int iLineStyleRow = 0; iLineStyleRow < pObjectItem->rowCount(); iLineStyleRow++)
        {
            QStandardItem* pLayerNameItem = pObjectItem->child(iLineStyleRow, MV_COLUMN_IMPORTED_OBJECT);
            QStandardItem* pProjectLineItem = pObjectItem->child(iLineStyleRow, MV_COLUMN_PROJECT_LINE);
            DBG_WARN_AND_CONTINUE_UNLESS(pLayerNameItem && pProjectLineItem, L"LineStyleItem为空",L"GDMPLab",L"2024-03-30");

            QVariant varCategoryId = pLayerNameItem->data(MVLineStyleItemDataRole_CategoryId);
            DBG_WARN_AND_CONTINUE_UNLESS(varCategoryId.isValid(), L"varCategoryId无效",L"GDMPLab",L"2024-03-30");
            UniIdentity categoryId(varCategoryId.toUuid());
            DBG_WARN_AND_CONTINUE_UNLESS(categoryId.IsValid(), L"categoryId无效",L"GDMPLab",L"2024-03-30");

            ElementId gstyleIdInDoc = pDoc->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(categoryId);
            IGraphicsStyle* pDocStyle = quick_cast<IGraphicsStyle>(pDoc->GetElement(gstyleIdInDoc));
            DBG_WARN_AND_CONTINUE_UNLESS(pDocStyle, L"pDocStyle为空",L"GDMPLab",L"2024-03-30");

            // 文档级样式数据
            OwnerPtr<IGraphicsStyleData> opDocStyleData = pDocStyle->GetGraphicsStyleData();

            // visibility
            QVariant varVisible = pLayerNameItem->data(MVLineStyleItemDataRole_LineVisible);
            DBG_WARN_AND_CONTINUE_UNLESS(varVisible.isValid(), L"varVisible无效",L"GDMPLab",L"2024-03-30");

            if (gstyleIdInDoc.IsValid())
                m_pCurrentModelView->SetElementsVisibilityByCategoryUid(categoryId, varVisible.toBool());

            // project line
            QVariant varProjectLineChanged = pProjectLineItem->data(MVLineStyleItemDataRole_ValueChangedFlag);
            if (varProjectLineChanged.isValid() && varProjectLineChanged.toBool())
            {
                IModelView *pModelView = m_pCurrentModelView;
                DBG_WARN_AND_CONTINUE_UNLESS(pModelView, L"dynamic_cast<ModelView*>(m_pCurrentModelView) 返回空指针",L"GDMPLab",L"2024-03-30");

                // 获取视图的类别样式重载数据， 如果视图没有重载目标类别样式，则获取文档级对应类别的样式数据
                std::pair<OwnerPtr<IGraphicsStyleDataOverrideItems>, OwnerPtr<IGraphicsStyleData>> opGStyleInfos = pModelView->GetGraphicsStyleOverrideByCategoryUid(pDocStyle->GetTargetCategoryUid());
                
                QVariant varLineWidth = pProjectLineItem->data(MVLineStyleItemDataRole_LineWidth);
                QVariant varLineColor = pProjectLineItem->data(MVLineStyleItemDataRole_LineColor);
                QVariant varLineColorIsOverridden = pProjectLineItem->data(MVLineStyleItemDataRole_LineColorIsOverridden);
                QVariant varLineType = pProjectLineItem->data(MVLineStyleItemDataRole_LineType);

                int lineWidth = varLineWidth.toInt();
                if (lineWidth == -1)
                {
                    opGStyleInfos.first->OverrideProjectionLineWidth(false);
                    opGStyleInfos.second->SetProjectionLineWidth(opDocStyleData->GetProjectionLineWidth());
                }
                else
                {
                    opGStyleInfos.first->OverrideProjectionLineWidth(true);
                    opGStyleInfos.second->SetProjectionLineWidth(lineWidth);
                }

                if (!varLineColorIsOverridden.toBool())
                {
                    opGStyleInfos.first->OverrideProjectionLineColor(false);
                    opGStyleInfos.second->SetProjectionLineColor(opDocStyleData->GetProjectionLineColor());
                }
                else
                {
                    opGStyleInfos.first->OverrideProjectionLineColor(true);
                    QColor qcolor = varLineColor.value<QColor>();
                    Color lineColor(qcolor.red(), qcolor.green(), qcolor.blue());
                    opGStyleInfos.second->SetProjectionLineColor(lineColor);
                }

                std::wstring lineType = varLineType.toString().toStdWString();
                if (lineType.empty())
                {
                    opGStyleInfos.first->OverrideProjectionLineTypeName(false);
                    opGStyleInfos.second->SetProjectionLineTypeName(opDocStyleData->GetProjectionLineTypeName());
                }
                else
                {
                    opGStyleInfos.first->OverrideProjectionLineTypeName(true);
                    opGStyleInfos.second->SetProjectionLineTypeName(lineType);
                }

                // 更新视图样式重载数据
                pModelView->OverrideGraphicsStyleByCategoryUid(pDocStyle->GetTargetCategoryUid(), *opGStyleInfos.first, *opGStyleInfos.second);
            }
        }
    }
}

bool ImportedObjectModelViewStylePage::InitUI(IModelView* pCurrentModelView, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories)
{
    m_pCurrentModelView = pCurrentModelView;

    std::list<ImportedObjectStyleData> objectStyles;
    bool bOk = ImportedObjectStylePageUtils::GetModelViewContent(m_pCurrentModelView, categories, objectStyles);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"获取Style失败",L"GDMPLab",L"2024-03-30");

    bOk = BuildTreeModel(objectStyles);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"BuildTreeModel失败",L"GDMPLab",L"2024-03-30");

    bOk = SetDelegates();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"SetDelegates失败",L"GDMPLab",L"2024-03-30");

    return true;
}

bool ImportedObjectModelViewStylePage::BuildTreeModel(const std::list<ImportedObjectStyleData>& objectStyles)
{
    m_pTreeModel->clear();

    m_pTreeModel->setColumnCount(2);
    m_pTreeModel->setHeaderData(MV_COLUMN_IMPORTED_OBJECT, Qt::Horizontal, QString::fromStdWString(GBMP_TR(L"导入对象")));
    m_pTreeModel->setHeaderData(MV_COLUMN_PROJECT_LINE, Qt::Horizontal, QString::fromStdWString(GBMP_TR(L"投影线")));

    int objectRowIndex = 0;
    FOR_EACH(itrObject, objectStyles)
    {
        std::wstring objectName = itrObject.ObjectName;

        OwnerPtr<QStandardItem> opObjectItem = NEW_AS_OWNER_PTR(QStandardItem, QString::fromStdWString(objectName));
        opObjectItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
        bool bObjectVisible = itrObject.ObjectVisible;
        opObjectItem->setCheckState(bObjectVisible? Qt::Checked : Qt::Unchecked);
        opObjectItem->setData(bObjectVisible, MVLineStyleItemDataRole_ObjectVisible);

        int layerRowIndex = 0;
        FOR_EACH(itrLineStyle, itrObject.LineStyles)
        {
            UniIdentity categoryId = itrLineStyle.CategoryId;
            QUuid categoryUid(categoryId.GetGuid());

            OwnerPtr<QStandardItem> opLayerNameItem = NEW_AS_OWNER_PTR(QStandardItem, QString::fromStdWString(itrLineStyle.LayerName));
            opLayerNameItem->setData(categoryUid, MVLineStyleItemDataRole_CategoryId);
            opLayerNameItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
            opLayerNameItem->setCheckState(itrLineStyle.Visible? Qt::Checked : Qt::Unchecked);
            opLayerNameItem->setData(itrLineStyle.Visible, MVLineStyleItemDataRole_LineVisible);
            opObjectItem->setChild(layerRowIndex, MV_COLUMN_IMPORTED_OBJECT, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opLayerNameItem));

            std::wstring displayProjectLine;
            if ((itrLineStyle.LineWidth == -1) && !itrLineStyle.LineColorIsOverridden && itrLineStyle.LineType.empty())
                displayProjectLine = GBMP_TR(L"无替换");
            OwnerPtr<QStandardItem> opProjectLineItem = NEW_AS_OWNER_PTR(QStandardItem, QString::fromStdWString(displayProjectLine));
            opProjectLineItem->setFlags(Qt::ItemIsEnabled);
            opProjectLineItem->setData(itrLineStyle.LineWidthInherited, MVLineStyleItemDataRole_LineWidthInherited);
            opProjectLineItem->setData(itrLineStyle.LineWidth, MVLineStyleItemDataRole_LineWidth);
            QColor lineColorInherited(itrLineStyle.LineColorInherited.R, itrLineStyle.LineColorInherited.G, itrLineStyle.LineColorInherited.B);
            QColor lineColor(itrLineStyle.LineColor.R, itrLineStyle.LineColor.G, itrLineStyle.LineColor.B);
            opProjectLineItem->setData(lineColorInherited, MVLineStyleItemDataRole_LineColorInherited);
            opProjectLineItem->setData(lineColor, MVLineStyleItemDataRole_LineColor);
            opProjectLineItem->setData(itrLineStyle.LineColorIsOverridden, MVLineStyleItemDataRole_LineColorIsOverridden);
            opProjectLineItem->setData(QString::fromStdWString(itrLineStyle.LineTypeInherited), MVLineStyleItemDataRole_LineTypeInherited);
            opProjectLineItem->setData(QString::fromStdWString(itrLineStyle.LineType), MVLineStyleItemDataRole_LineType);
            opObjectItem->setChild(layerRowIndex, MV_COLUMN_PROJECT_LINE, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opProjectLineItem));

            layerRowIndex++;
        }

        m_pTreeModel->setItem(objectRowIndex, MV_COLUMN_IMPORTED_OBJECT, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opObjectItem));
        {
            OwnerPtr<QStandardItem> opDummyProjectLineItem = NEW_AS_OWNER_PTR(QStandardItem);
            opDummyProjectLineItem->setFlags(Qt::NoItemFlags);
            m_pTreeModel->setItem(objectRowIndex, MV_COLUMN_PROJECT_LINE, TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opDummyProjectLineItem));
        }

        objectRowIndex++;
    }

    connect(m_pTreeModel, &QStandardItemModel::itemChanged, this, &ImportedObjectModelViewStylePage::OnItemDataChanged);

    m_pTreeView->setModel(m_pTreeModel);
    return true;
}

bool ImportedObjectModelViewStylePage::SetDelegates()
{
    // project line
    LineStyleItemDelegate* pLineStyleItemDelegate = NEW_AS_QT_CHILD(LineStyleItemDelegate, this);
    m_pTreeView->setItemDelegateForColumn(MV_COLUMN_PROJECT_LINE, pLineStyleItemDelegate);

    connect(m_pTreeView, &QTreeView::clicked, this, &ImportedObjectModelViewStylePage::OnItemClicked);

    return true;
}

void ImportedObjectModelViewStylePage::OnItemClicked(const QModelIndex& index)
{
    if (index.column() == MV_COLUMN_PROJECT_LINE)
    {
        QStandardItem* pItem = m_pTreeModel->itemFromIndex(index);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pItem, L"pItem为空",L"GDMPLab",L"2024-03-30");

        QVariant varLineWidthInherited = pItem->data(MVLineStyleItemDataRole_LineWidthInherited);
        QVariant varLineWidth = pItem->data(MVLineStyleItemDataRole_LineWidth);
        QVariant varLineColorInherited = pItem->data(MVLineStyleItemDataRole_LineColorInherited);
        QVariant varLineColor = pItem->data(MVLineStyleItemDataRole_LineColor);
        QVariant varLineColorIsOverridden = pItem->data(MVLineStyleItemDataRole_LineColorIsOverridden);
        QVariant varLineTypeInherited = pItem->data(MVLineStyleItemDataRole_LineTypeInherited);
        QVariant varLineType = pItem->data(MVLineStyleItemDataRole_LineType);
        if (!varLineWidthInherited.isValid() || !varLineWidth.isValid() || !varLineColorInherited.isValid() || !varLineColor.isValid() ||
            !varLineColorIsOverridden.isValid() || !varLineTypeInherited.isValid() || !varLineType.isValid())
            return;

        int lastLineWidth = varLineWidth.toInt();

        QColor qcolor = varLineColor.value<QColor>();
        Color lastLineColor(qcolor.red(), qcolor.green(), qcolor.blue());
        bool lastLineColorIsOverridden = varLineColorIsOverridden.toBool();

        std::wstring lastLineType = varLineType.toString().toStdWString();

        LineStyleDlg dlg;
        dlg.SetLineWidth(lastLineWidth);
        dlg.SetLineColorOverride(lastLineColorIsOverridden);
        dlg.SetLineColor(lastLineColor);
        dlg.SetLineType(lastLineType.empty()? GBMP_TR(L"无替换") : lastLineType);
        dlg.Init();
        if (dlg.exec() == QDialog::Accepted)
        {
            double retLineWidth = dlg.GetLineWidth();

            bool retLineColorIsOverridden = dlg.GetLineColorOverride();
            Color retLineColor = dlg.GetLineColor();

            std::wstring retLineType = dlg.GetLineType();
            if (retLineType == GBMP_TR(L"无替换"))
                retLineType.clear();

            bool hasAnyChanges = false;
            if (lastLineWidth != retLineWidth)
            {
                m_pTreeModel->setData(index, retLineWidth, MVLineStyleItemDataRole_LineWidth);
                hasAnyChanges = true;
            }
            if (lastLineColorIsOverridden != retLineColorIsOverridden)
            {
                m_pTreeModel->setData(index, retLineColorIsOverridden, MVLineStyleItemDataRole_LineColorIsOverridden);
                hasAnyChanges = true;
            }
            if (lastLineColor != retLineColor)
            {
                QColor color(retLineColor.R, retLineColor.G, retLineColor.B);
                m_pTreeModel->setData(index, color, MVLineStyleItemDataRole_LineColor);
                hasAnyChanges = true;
            }
            if (lastLineType != retLineType)
            {
                m_pTreeModel->setData(index, QString::fromStdWString(retLineType), MVLineStyleItemDataRole_LineType);
                hasAnyChanges = true;
            }
            if (hasAnyChanges)
            {
                m_pTreeModel->setData(index, true, MVLineStyleItemDataRole_ValueChangedFlag);
            }
            if (retLineWidth != -1 || retLineColorIsOverridden || !retLineType.empty())
            {
                pItem->setText("");
            }
            else
            {
                pItem->setText(QString::fromStdWString(GBMP_TR(L"无替换")));
            }
        }
    }
}

void ImportedObjectModelViewStylePage::OnItemDataChanged(QStandardItem *item)
{
    QModelIndex index = item->index();

    // visibility changes?
    if (index.column() == MV_COLUMN_IMPORTED_OBJECT)
    {
        QVariant varLineVisible = item->data(MVLineStyleItemDataRole_LineVisible);
        if (varLineVisible.isValid())
        {
            bool lastVisible = varLineVisible.toBool();
            bool newVisible = (item->checkState() == Qt::Checked);
            if (lastVisible != newVisible)
            {
                m_pTreeModel->setData(index, newVisible, MVLineStyleItemDataRole_LineVisible);
                m_pTreeModel->setData(index, true, MVLineStyleItemDataRole_ValueChangedFlag);
            }
        }

        QVariant varObjectVisible = item->data(MVLineStyleItemDataRole_ObjectVisible);
        if (varObjectVisible.isValid())
        {
            bool lastVisible = varObjectVisible.toBool();
            bool newVisible = (item->checkState() == Qt::Checked);
            if (lastVisible != newVisible)
            {
                m_pTreeModel->setData(index, newVisible, MVLineStyleItemDataRole_ObjectVisible);
                m_pTreeModel->setData(index, true, MVLineStyleItemDataRole_ValueChangedFlag);
            }
        }
    }
}

//////////////////////////////////////////////////////////////////////////
bool ImportedObjectStylePageUtils::GetProjectContent(IDocument* pDoc, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories, std::list<ImportedObjectDocumentStylePage::ImportedObjectStyleData>& objectStyles)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    objectStyles.clear();

    FOR_EACH(itrObject, categories)
    {
        ImportedObjectDocumentStylePage::ImportedObjectStyleData objectStyle;
        objectStyle.ObjectName = itrObject.first;

        FOR_EACH(itrCategoryId, itrObject.second)
        {
            const UniIdentity& uid = itrCategoryId;

            const ICategory* pCategory = ICategoryLibrary::Get(pDoc)->GetCategory(uid);
            DBG_WARN_AND_CONTINUE_UNLESS(pCategory, L"pCategory为空",L"GDMPLab",L"2024-03-30");

            ElementId styleId = pDoc->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(uid);
            const IGraphicsStyle* pStyle = quick_cast<IGraphicsStyle>(pDoc->GetElement(styleId));
            DBG_WARN_AND_CONTINUE_UNLESS(pStyle, L"pStyle为空",L"GDMPLab",L"2024-03-30");

            std::wstring familyName, layerName;
            bool bOk = ImportedObjectStylePageUtils::GetFamilyNameAndLayerNameFromCategory(pCategory, familyName, layerName);
            DBG_WARN_AND_CONTINUE_UNLESS(bOk, L"GetCADFileNameWithExtensionAndLayerNameFromCategory失败",L"GDMPLab",L"2024-03-30");

            ImportedObjectDocumentStylePage::LineStyleData lineStyle;
            lineStyle.CategoryId = itrCategoryId;
            lineStyle.LayerName = layerName;
            OwnerPtr<IGraphicsStyleData> opCurStyleData = pStyle->GetGraphicsStyleData();
            lineStyle.LineWidth = opCurStyleData->GetProjectionLineWidth();
            lineStyle.LineColor = opCurStyleData->GetProjectionLineColor();
            lineStyle.LineType = opCurStyleData->GetProjectionLineTypeName();
            objectStyle.LineStyles.push_back(lineStyle);
        }

        objectStyles.push_back(objectStyle);
    }

    return true;
}

bool ImportedObjectStylePageUtils::GetModelViewContent(IModelView* pModelView, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories, std::list<ImportedObjectModelViewStylePage::ImportedObjectStyleData>& objectStyles)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pModelView->GetDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    objectStyles.clear();

    FOR_EACH(itrObject, categories)
    {
        ImportedObjectModelViewStylePage::ImportedObjectStyleData objectStyle;
        const std::wstring& objectName = itrObject.first;
        objectStyle.ObjectName = objectName;
        objectStyle.ObjectVisible = false;
        IFamily* family = IFamily::GetFamilyByName(pDoc, objectName);
        if (family)
        {
            auto instanceTypes = family->GetInstanceTypes();
            FOR_EACH(itrInstanceType, instanceTypes)
            {
                const std::vector<IInstance*> instances = itrInstanceType->GetAllInstances();
                FOR_EACH(itrInstance, instances)
                {
                    if (pModelView->GetElementVisibilityByElementId(itrInstance->GetElementId()))
                    {
                        objectStyle.ObjectVisible = true;
                        break;
                    }
                }
            }
        }

        FOR_EACH(pItrCategoryId, itrObject.second)
        {
            const UniIdentity& uid = pItrCategoryId;

            const ICategory* pCategory = ICategoryLibrary::Get(pDoc)->GetCategory(uid);
            DBG_WARN_AND_CONTINUE_UNLESS(pCategory, L"pCategory为空",L"GDMPLab",L"2024-03-30");

            ElementId docGStyleId = pDoc->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(uid); //visibilityGraphics.GetGraphicsStyle(uid);
            DBG_WARN_AND_CONTINUE_UNLESS(docGStyleId.IsValid(), L"HasVisibility失败",L"GDMPLab",L"2024-03-30");

            IGraphicsStyle* pDocStyle = quick_cast<IGraphicsStyle>(pDoc->GetElement(docGStyleId));// DocUtil::GetElement<IGraphicsStyleInternal>(pDoc, styleId);
            DBG_WARN_AND_CONTINUE_UNLESS(pDocStyle, L"pDocStyle为空",L"GDMPLab",L"2024-03-30");

            // 文档级的类别样式数据
            OwnerPtr<IGraphicsStyleData> opDocStyleData = pDocStyle->GetGraphicsStyleData();

            // 视图级的类别样式数据、重载信息
            std::pair<OwnerPtr<IGraphicsStyleDataOverrideItems>, OwnerPtr<IGraphicsStyleData>> opModelViewGStyleInfo =
                pModelView->GetGraphicsStyleOverrideByCategoryUid(pDocStyle->GetTargetCategoryUid());

            std::wstring familyName, layerName;
            bool bOk = ImportedObjectStylePageUtils::GetFamilyNameAndLayerNameFromCategory(pCategory, familyName, layerName);
            DBG_WARN_AND_CONTINUE_UNLESS(bOk, L"GetLayerNameFromCategory失败",L"GDMPLab",L"2024-03-30");

            bool visible = pModelView->GetElementsVisibilityByCategoryUid(uid);

            ImportedObjectModelViewStylePage::LineStyleData lineStyle;
            lineStyle.CategoryId = pItrCategoryId;
            lineStyle.LayerName = layerName;
            lineStyle.Visible = visible;

            lineStyle.LineWidthInherited = opDocStyleData->GetProjectionLineWidth();
            if (opModelViewGStyleInfo.first->IsProjectionLineWidthOverridden())
            {
                lineStyle.LineWidth = opModelViewGStyleInfo.second->GetProjectionLineWidth();
            }
            else
            {
                lineStyle.LineWidth = -1;
            }

            lineStyle.LineColorInherited = opDocStyleData->GetProjectionLineColor();
            if (opModelViewGStyleInfo.first->IsProjectionLineColorOverridden())
            {
                lineStyle.LineColorIsOverridden = true;
                lineStyle.LineColor = opModelViewGStyleInfo.second->GetProjectionLineColor();
            }
            else
            {
                lineStyle.LineColorIsOverridden = false;
            }

            lineStyle.LineTypeInherited = opDocStyleData->GetProjectionLineTypeName();
            if (opModelViewGStyleInfo.first->IsProjectionLineTypeNameOverridden())
            {
                lineStyle.LineType = opModelViewGStyleInfo.second->GetProjectionLineTypeName();
            }
            else
            {
                lineStyle.LineType = L"";
            }

            objectStyle.LineStyles.push_back(lineStyle);
        }

        objectStyles.push_back(objectStyle);
    }

    return true;
}

bool ImportedObjectStylePageUtils::GetFamilyNameAndLayerNameFromCategory(const ICategory* pCategory, std::wstring & familyName, std::wstring & layerName)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCategory, L"pCategory为空",L"GDMPLab",L"2024-03-30");

    // category name is composed as "dxf file name;layer name", see GmImportedObjectFamilyUtils::CreateDxfEntities()
    const std::wstring& categoryName = pCategory->GetName();

    size_t semicolonPosition = categoryName.find(L";");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(semicolonPosition != -1, L"导入对象的Catetgory名字不符合规则，规则是：<Family Name>;<Layer Name>",L"GDMPLab",L"2024-03-30");
    
    familyName = categoryName.substr(0, semicolonPosition);
    layerName = categoryName.substr(semicolonPosition + 1);
    return true;
}
